package guijavacommander;

import guijavacommander.actions.*;

import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Comparator;

/**
 * User: Deady
 * Date: 15.07.2009
 * Time: 13:32:18
 */
public class JavaCommander extends JFrame {

    public static JavaCommander instance;
    private JSplitPane rootSplitPane;
    private FilePanel activePanel;
    private FilePanel inactivePanel;


    public JavaCommander() {

        instance = this;

        setSize(800, 600);
        setTitle("Java Commander");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JScrollPane sp = new JScrollPane();
        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        final JScrollPane sp2 = new JScrollPane();
        sp2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);

        final FilePanel l = createFilePanel();
        final FilePanel l2 = createFilePanel();

        final JTabbedPane tabbed1 = createTabs(l);
        JTabbedPane tabbed2 = createTabs(l2);

        rootSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tabbed1, tabbed2);


        getContentPane().add(rootSplitPane, BorderLayout.CENTER);
        rootSplitPane.setDividerLocation(JavaCommander.this.getWidth() / 2);
        rootSplitPane.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                rootSplitPane.setDividerLocation(JavaCommander.this.getWidth() / 2);
            }
        });


        setFocusTraversalPolicy(new FilePanelFocusTraversalPolicy());

        l.requestFocus();


    }

    private JTabbedPane createTabs(FilePanel panel) {
        final JTabbedPane tabbed1 = new JTabbedPane(JTabbedPane.TOP);
        tabbed1.setFocusable(false);
        tabbed1.addTab(panel.getCurrentFolder().getName(), panel);

        panel.setTabCaptionListener(new TabCaptionListener() {
            public void setTabCaption(String caption) {
                tabbed1.setTitleAt(0, caption);
            }
        });


        tabbed1.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    final FilePanel l = createFilePanel();
                    tabbed1.addTab(l.getCurrentFolder().getName(), l);
                    l.setTabCaptionListener(new TabCaptionListener() {
                        public void setTabCaption(String caption) {
                            tabbed1.setTitleAt(tabbed1.getTabCount(), caption);
                        }
                    });
                }
            }
        });
        return tabbed1;
    }

    private FilePanel createFilePanel() {
        FilePanel l = null;
        try {
            l = new FilePanel(new File("/"));
            initPanel(l, l.getFileList());
            l.setCurrentFolder(new File(System.getProperty("user.home")));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return l;
    }

    private void initPanel(final FilePanel parent, final TreeList l) {

        l.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
                    new OpenFileAction(parent).actionPerformed(null);
                }
            }
        });

        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), "renameFile");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0), "viewFile");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0), "editFile");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0), "copyFiles");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F6, 0), "moveFiles");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0), "createFolder");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F8, 0), "removeFiles");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_MULTIPLY, 0), "inverseSelection");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "removeFiles");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "openFile");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_DOWN_MASK), "selectAll");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK), "refresh");
        l.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_DOWN_MASK), "swapPanels");


        l.getActionMap().put("viewFile", new ViewFileAction());
        l.getActionMap().put("editFile", new EditFileAction(parent));
        //l.getActionMap().put("copyFiles", new CopyGnomeAction());
        l.getActionMap().put("copyFiles", new CopyOldWayAction());
        l.getActionMap().put("selectAll", new SelectAllAction(parent));
        l.getActionMap().put("inverseSelection", new InverseSelection(parent));
        l.getActionMap().put("renameFile", new RenameFileAction(parent));
        l.getActionMap().put("openFile", new OpenFileAction(parent));
        l.getActionMap().put("refresh", new RefreshAction(parent));
        l.getActionMap().put("moveFiles", new MoveFilesAction());
        l.getActionMap().put("removeFiles", new RemoveFilesAction());
        l.getActionMap().put("createFolder", new CreateDirAction(parent));
        l.getActionMap().put("swapPanels", new SwapPanelsAction());

        l.addFocusListener(new FocusListener() {
            public void focusGained(FocusEvent e) {
                l.repaint();
                activePanel = parent;
            }

            public void focusLost(FocusEvent e) {
                l.repaint();
                inactivePanel = parent;
            }
        });
    }

    private void swapFocus() {
        JTabbedPane tabs1 = (JTabbedPane) rootSplitPane.getLeftComponent();
        FilePanel panel1 = (FilePanel) tabs1.getSelectedComponent();
        if (!panel1.hasFocus()) {
            panel1.requestFocus();
        } else {
            tabs1 = (JTabbedPane) rootSplitPane.getRightComponent();
            panel1 = (FilePanel) tabs1.getSelectedComponent();
            panel1.requestFocus();
        }
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        JavaCommander cmd = new JavaCommander();
        cmd.setVisible(true);
    }


    public void refreshPanels() {
        JTabbedPane p = (JTabbedPane) rootSplitPane.getLeftComponent();
        FilePanel pp = (FilePanel) p.getSelectedComponent();
        pp.refresh();

        p = (JTabbedPane) rootSplitPane.getRightComponent();
        pp = (FilePanel) p.getSelectedComponent();
        pp.refresh();

    }

    public void swapPanels() {
        JTabbedPane tabs1 = (JTabbedPane) rootSplitPane.getLeftComponent();
        FilePanel panel1 = (FilePanel) tabs1.getSelectedComponent();
        int index1 = tabs1.getSelectedIndex();

        boolean leftInFocus = panel1.hasFocus();

        JTabbedPane tabs2 = (JTabbedPane) rootSplitPane.getRightComponent();
        FilePanel panel2 = (FilePanel) tabs2.getSelectedComponent();
        int index2 = tabs2.getSelectedIndex();

        TabCaptionListener l = panel1.getTabCaptionListener();
        panel1.setTabCaptionListener(panel2.getTabCaptionListener());
        panel2.setTabCaptionListener(l);


        tabs2.setComponentAt(index2, new JPanel());
        tabs1.setComponentAt(index1, panel2);
        tabs2.setComponentAt(index2, panel1);
        panel1.updateCurrentFolder();
        panel2.updateCurrentFolder();

        if (leftInFocus) {
            panel1.requestFocus();
        } else {
            panel2.requestFocus();
        }
    }


    public FilePanel getActivePanel() {
        return activePanel;
    }

    public FilePanel getInactivePanel() {
        return inactivePanel;
    }

    private static class MyListDataListener implements ListDataListener {
        private final TreeList l;

        public MyListDataListener(TreeList l) {
            this.l = l;
        }

        public void intervalAdded(ListDataEvent e) {
        }

        public void intervalRemoved(ListDataEvent e) {
        }

        public void contentsChanged(ListDataEvent e) {
            l.setCurrentElement(0);
        }
    }


    private class FilePanelFocusTraversalPolicy extends SortingFocusTraversalPolicy {
        public FilePanelFocusTraversalPolicy() {
            super(new Comparator<Component>() {
                public int compare(Component o1, Component o2) {
                    if (o1 instanceof TreeList && !(o2 instanceof TreeList)) {
                        return -1;
                    } else if (!(o1 instanceof TreeList) && (o2 instanceof TreeList)) {
                        return 1;
                    } else if (!(o1 instanceof TreeList && o2 instanceof TreeList)) {
                        return 0;
                    } else {
                        JTabbedPane p = (JTabbedPane) JavaCommander.this.rootSplitPane.getLeftComponent();
                        FilePanel l = (FilePanel) p.getSelectedComponent();
                        TreeList list = l.getFileList();
                        if (o1.equals(list)) {
                            return -1;
                        } else {
                            return 1;
                        }
                    }
                }

            });
        }

        @Override
        protected boolean accept(Component aComponent) {
            return aComponent instanceof TreeList;
        }
    }
}
